/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package desarrollosoft.ghce.vista.implementaciones;

import desarrollosoft.ghce.entidades.Paciente;
import desarrollosoft.ghce.entidades.Sexo;
import desarrollosoft.ghce.entidades.TipoDocumento;
import desarrollosoft.ghce.servicio.interfaces.IParserExcepciones;
import desarrollosoft.ghce.servicio.interfaces.IServicioExportarHistoriaClinica;
import desarrollosoft.ghce.servicio.interfaces.IServicioPacientes;
import desarrollosoft.ghce.vista.interfaces.Avisable;
import desarrollosoft.ghce.vista.interfaces.Cambiable;
import desarrollosoft.ghce.vista.interfaces.Estado;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Button;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Filedownload;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

/**
 *
 * @author ariel
 */
@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class ControladoraAdministracionPacientes extends SelectorComposer<Window> implements Avisable {

    @WireVariable("servicioPacientes")
    private IServicioPacientes servicioPacientes;

    @WireVariable("parserExcepcionesPaciente")
    private IParserExcepciones parserExcepcionesPaciente;
    
    @WireVariable("servicioExportarHistoriaClinica")
    private IServicioExportarHistoriaClinica servicioExportarHistoria;
    
    private Cambiable cambiable;

    private Estado estado;

    private List<String> listaTiposDato;

    private List<Paciente> listaPacientes;

    private List<Sexo> listaSexos;

    private List<TipoDocumento> listaTiposDocumento;

    @Wire
    private Textbox textboxDato;

    @Wire
    private Combobox comboboxTipoDato;

    @Wire
    private Listbox listboxPacientes;

    @Wire
    private Textbox textboxApellidos;

    @Wire
    private Textbox textboxNombres;

    @Wire
    private Textbox textboxNumeroIdentificacion;

    @Wire
    private Combobox comboboxTipoIdentificacion;

    @Wire
    private Combobox comboboxSexo;

    @Wire
    private Datebox dateboxFechaNacimiento;

    @Wire
    private Textbox textboxOcupacion;

    @Wire
    private Textbox textboxDomicilio;

    @Wire
    private Textbox textboxEdad;

    @Wire
    private Button botonBuscar;

    @Wire
    private Button botonCrear;

    @Wire
    private Button botonModificar;

    @Wire
    private Button botonEliminar;

    @Wire
    private Button botonReactivar;
    
    @Wire
    private Button botonDescargarHistoriaClinica;
    
    @Wire
    private Button botonVerHistoriaClinica;

    @Wire
    private Button botonGuardar;

    @Wire
    private Button botonCancelar;

    @Override
    public void doAfterCompose(Window comp) throws Exception {
        hacerAntesDeDibujar();
        super.doAfterCompose(comp); // wire variables and event listners
        hacerDespuesDeDibujar();
    }

    private void hacerAntesDeDibujar() {
        Execution ejecucion = Executions.getCurrent();
        cambiable = (Cambiable) ejecucion.getArg().get("controladoraPrincipal");

        // inicializo listas constantes
        listaTiposDato = servicioPacientes.listaTiposDatosBuscables();
        listaSexos = servicioPacientes.obtenerTodosSexo();
        listaTiposDocumento = servicioPacientes.obtenerTiposDocumento();

        // la lista de pacientes esta vacia inicialmente
        listaPacientes = new ArrayList<>();
    }

    private void hacerDespuesDeDibujar() {
        //listboxPacientes.setModel(new ListModelList<>(listaPacientes)); // al pepe
        comboboxTipoDato.setModel(new ListModelList<>(listaTiposDato));
        comboboxTipoIdentificacion.setModel(new ListModelList<>(listaTiposDocumento));
        comboboxSexo.setModel(new ListModelList<>(listaSexos));
        camposSoloLectura(true);
        setearEstadoBotones(Estado.BUSCANDO);
    }

    @Listen("onSelect = #listboxPacientes")
    public void seleccionaronPaciente() {
        Paciente pacienteSeleccionado = listboxPacientes.getSelectedItem().getValue();
        mostrarDatos(pacienteSeleccionado);
        setearEstadoBotones(Estado.PACIENTE_SELECCIONADO);
    }

    private void mostrarDatos(Paciente paciente) {
        textboxApellidos.setValue(paciente.getApellidos());
        textboxNombres.setValue(paciente.getNombres());
        textboxDomicilio.setValue(paciente.getDomicilio());
        textboxNumeroIdentificacion.setValue(paciente.getNumeroIdentificacion());
        textboxOcupacion.setValue(paciente.getOcupacion());
        comboboxSexo.setSelectedIndex(listaSexos.indexOf(paciente.getSexo()));
        comboboxTipoIdentificacion.setSelectedIndex(listaTiposDocumento.indexOf(paciente.getTipoDocumento()));
        textboxEdad.setValue(String.valueOf(paciente.getEdad()));
        dateboxFechaNacimiento.setValue(paciente.getFechaNacimiento());
    }

    private void limpiarCampos() {
        textboxApellidos.setValue(null);
        textboxNombres.setValue(null);
        textboxDomicilio.setValue(null);
        textboxNumeroIdentificacion.setValue(null);
        textboxOcupacion.setValue(null);
        comboboxSexo.setSelectedIndex(-1);
        comboboxTipoIdentificacion.setSelectedIndex(-1);
        textboxEdad.setValue(null);
        dateboxFechaNacimiento.setValue(null);
    }

    private void camposSoloLectura(boolean valor) {
        textboxApellidos.setReadonly(valor);
        textboxNombres.setReadonly(valor);
        textboxDomicilio.setReadonly(valor);
        textboxNumeroIdentificacion.setReadonly(valor);
        textboxOcupacion.setReadonly(valor);
        comboboxSexo.setReadonly(valor);
        comboboxSexo.setButtonVisible(!valor);
        comboboxTipoIdentificacion.setReadonly(valor);
        comboboxTipoIdentificacion.setButtonVisible(!valor);
        dateboxFechaNacimiento.setReadonly(valor);
        dateboxFechaNacimiento.setButtonVisible(!valor);
    }

    private void setearEstadoBotones(Estado estado) {
        this.estado = estado;
        switch (estado) {
            case BUSCANDO:
                botonBuscar.setDisabled(false);
                botonCrear.setDisabled(false);

                botonModificar.setDisabled(true);
                botonEliminar.setDisabled(true);
                botonVerHistoriaClinica.setDisabled(true);
                botonReactivar.setDisabled(true);
                botonDescargarHistoriaClinica.setDisabled(true);

                botonGuardar.setDisabled(true);
                botonCancelar.setDisabled(true);
                break;
            case PACIENTE_SELECCIONADO:
                botonBuscar.setDisabled(false);
                botonCrear.setDisabled(false);

                botonModificar.setDisabled(false);
                botonEliminar.setDisabled(false);
                botonVerHistoriaClinica.setDisabled(false);
                botonReactivar.setDisabled(false);
                botonDescargarHistoriaClinica.setDisabled(false);

                botonGuardar.setDisabled(true);
                botonCancelar.setDisabled(true);
                break;
            case CREANDO:
                botonBuscar.setDisabled(true);
                botonCrear.setDisabled(true);

                botonModificar.setDisabled(true);
                botonEliminar.setDisabled(true);
                botonVerHistoriaClinica.setDisabled(true);
                botonReactivar.setDisabled(true);
                botonDescargarHistoriaClinica.setDisabled(true);

                botonGuardar.setDisabled(false);
                botonCancelar.setDisabled(false);
                break;
            case MODIFICANDO:
                botonBuscar.setDisabled(true);
                botonCrear.setDisabled(true);

                botonModificar.setDisabled(true);
                botonEliminar.setDisabled(true);
                botonVerHistoriaClinica.setDisabled(true);
                botonReactivar.setDisabled(true);
                botonDescargarHistoriaClinica.setDisabled(true);

                botonGuardar.setDisabled(false);
                botonCancelar.setDisabled(false);
                break;
        }
    }

    private Paciente obtenerDatosPaciente() {
        Paciente paciente = new Paciente();

        paciente.setNombres((textboxNombres.getValue().length() == 0) ? null : textboxNombres.getValue());
        paciente.setApellidos((textboxApellidos.getValue().length() == 0) ? null : textboxApellidos.getValue());
        paciente.setDomicilio((textboxDomicilio.getValue().length() == 0) ? null : textboxDomicilio.getValue());
        paciente.setNumeroIdentificacion((textboxNumeroIdentificacion.getValue().length() == 0) ? null : textboxNumeroIdentificacion.getValue());
        paciente.setOcupacion((textboxOcupacion.getValue().length() == 0) ? null : textboxOcupacion.getValue());
        paciente.setFechaNacimiento(dateboxFechaNacimiento.getValue());

        int posicionSexoSeleccionado = comboboxSexo.getSelectedIndex();
        int posicionTipoDocumentoSeleccionado = comboboxTipoIdentificacion.getSelectedIndex();

        if (posicionSexoSeleccionado < 0) {
            paciente.setSexo(null);
        } else {
            paciente.setSexo(listaSexos.get(posicionSexoSeleccionado));
        }

        if (posicionTipoDocumentoSeleccionado < 0) {
            paciente.setTipoDocumento(null);
        } else {
            paciente.setTipoDocumento(listaTiposDocumento.get(posicionTipoDocumentoSeleccionado));
        }

        return paciente;
    }

    @Listen("onClick = #botonBuscar")
    public void clickBotonBuscar() {
        limpiarCampos();
        camposSoloLectura(true);
        setearEstadoBotones(Estado.BUSCANDO);

        int indiceTipoDatoSeleccionado = comboboxTipoDato.getSelectedIndex();

        if (indiceTipoDatoSeleccionado < 0) {
            Messagebox.show("Seleccione un tipo de dato para realizar la búsqueda");
            return;
        }

        String dato = textboxDato.getValue();

        if (dato.length() == 0) {
            Messagebox.show("Ingrese un dato para buscar");
            return;
        }

        String tipoDato = listaTiposDato.get(indiceTipoDatoSeleccionado);
        try {
            listaPacientes = servicioPacientes.buscarPacienteActivo(dato, tipoDato);
            listboxPacientes.setModel(new ListModelList<>(listaPacientes));
        } catch (Exception ex) {
            Messagebox.show("Excepcion: \n" + ex.toString());
        }
    }

    @Listen("onClick = #botonCrear")
    public void clickBotonCrear() {
        limpiarCampos();
        camposSoloLectura(false);
        setearEstadoBotones(Estado.CREANDO);
    }

    @Listen("onClick = #botonModificar")
    public void clickBotonModificar() {
        Listitem li = listboxPacientes.getSelectedItem();
        if (li != null) {
            Paciente pacienteSeleccionado = li.getValue();
            if (pacienteSeleccionado != null) {
                if (pacienteSeleccionado.getBajaLogicaPaciente() != null) {
                    Messagebox.show("No puede modificar un paciente inactivo");
                    return;
                }
                setearEstadoBotones(Estado.MODIFICANDO);
                camposSoloLectura(false);
            }
        }
    }

    @Listen("onClick = #botonEliminar")
    public void clickBotonEliminar() {
        Paciente pacienteSeleccionado = listboxPacientes.getSelectedItem().getValue();
        if (pacienteSeleccionado.getBajaLogicaPaciente() == null) {
            Map<String, Object> argumentos = new HashMap<>();
            argumentos.put("pacienteElegido", pacienteSeleccionado);
            argumentos.put("avisable", this);
            Window ventana = (Window) Executions.createComponents("VentanaBajaLogicaPaciente.zul", null, argumentos);
            ventana.doModal();
        }
    }
    
    @Listen("onClick = #botonReactivar")
    public void clickBotonReactivar() {
        final Paciente pacienteSeleccionado = listboxPacientes.getSelectedItem().getValue();
        if (pacienteSeleccionado.getBajaLogicaPaciente() != null) {
            Messagebox.show("¿Confirma que desea Reactivar al paciente seleccionado?", "Confirme por favor",
                    Messagebox.YES | Messagebox.NO, Messagebox.QUESTION,
                    new EventListener() {
                        @Override
                        public void onEvent(Event evt) throws InterruptedException {
                            if (evt.getName().equals("onYes")) { // si confirma
                                try {
                                    servicioPacientes.reactivarPaciente(pacienteSeleccionado);
                                } catch (Exception e) {
                                    // habria q atravesar x el parser !!!!
                                    Messagebox.show(e.toString());
                                    return;
                                }
                                clickBotonBuscar(); // hago como que buscaron para actualizar la tabla
                            }
                        }
                    }
            );
        }
    }
    
    @Listen("onClick = #botonDescargarHistoriaClinica")
    public void clickBotonDescargarHistoriaClinica() {
        Listitem li = listboxPacientes.getSelectedItem();
        if (li != null) {
            Paciente pacienteSeleccionado = li.getValue();
            if (pacienteSeleccionado != null) {
                try {
                    File archivoTemporal = servicioExportarHistoria.obtenerArchivoHistoriaClinica(pacienteSeleccionado);
                    /* 2° argumento en null, para que determine solo el tipo de archivo */
                    Filedownload.save(archivoTemporal, null);
                } catch (FileNotFoundException ex) {
                    Messagebox.show("Error al DESCARGAR el archivo, intente nuevamente");
                } catch (Exception ex) {
                    Messagebox.show("Error al GENERAR el archivo, intente nuevamente");
                }
            }
        }
    }
    
    @Override
    public void seCerroVentanaHija(String nombre) {
        if (nombre.equals("bajaLogica")) {
            clickBotonBuscar();
        }
    }

    @Listen("onClick = #botonVerHistoriaClinica")
    public void clickBotonVerHistoriaClinica() {
        Paciente pacienteSeleccionado = listboxPacientes.getSelectedItem().getValue();
        Map<String,Object> argumentos = new HashMap<>();
        argumentos.put("pacienteElegido", pacienteSeleccionado); /* CONTROLAR EL TEMA DE QUE EN LA HC DE UN PACIENTE DADO DE BAJA, SOLO SE PUEDEN REALIZAR CONSULTAR */
        cambiable.cambiarConArgumentos("HistoriaClinica.zul", argumentos); // pido a la pantalla principal, cambiar el contenido
    }

    @Listen("onClick = #botonGuardar")
    public void clickBotonGuardar() {
        if (estado.equals(Estado.CREANDO)) {
            try {
                servicioPacientes.crearPaciente(obtenerDatosPaciente());
                Messagebox.show("Se creó el paciente correctamente");
                setearEstadoBotones(Estado.BUSCANDO);
                clickBotonBuscar(); // hago como que buscaron nuevamente, para refrescar la lista
            } catch (Exception ex) {
                Messagebox.show("Excepcion al crear paciente: " + parserExcepcionesPaciente.parsear(ex.toString()));
            }
        } else if (estado.equals(Estado.MODIFICANDO)) {
            Paciente pacienteSeleccionado = listboxPacientes.getSelectedItem().getValue();
            Paciente pacienteGuardar = obtenerDatosPaciente();
            pacienteGuardar.setId(pacienteSeleccionado.getId());

            try {
                servicioPacientes.modificarPaciente(pacienteGuardar);
                Messagebox.show("Se modificó el paciente correctamente");
                //setearEstadoBotones(Estado.PACIENTE_SELECCIONADO);
                clickBotonBuscar(); // hago como que buscaron nuevamente, para refrescar la lista
            } catch (Exception ex) {
                Messagebox.show("Excepcion al modificar paciente: " + parserExcepcionesPaciente.parsear(ex.toString()));
            }
        }
    }

    @Listen("onClick = #botonCancelar")
    public void clickBotonCancelar() {
        if (estado.equals(Estado.CREANDO)) {
            camposSoloLectura(true);
            setearEstadoBotones(Estado.BUSCANDO);
        } else if (estado.equals(Estado.MODIFICANDO)) {
            camposSoloLectura(true);
            setearEstadoBotones(Estado.PACIENTE_SELECCIONADO);
        }
    }
    
}
